package com.joelapenna.foursquared;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.joelapenna.foursquare.Foursquare;
import com.joelapenna.foursquare.error.FoursquareException;
import com.joelapenna.foursquare.types.Category;
import com.joelapenna.foursquare.types.Group;
import com.joelapenna.foursquare.util.CategoryUtils;
import com.joelapenna.foursquared.preferences.Preferences;
import com.joelapenna.foursquared.util.NotificationsUtil;
import com.joelapenna.foursquared.widget.CategoryListAdapter;
import com.joelapenna.foursquared.widget.SeparatedListAdapter;

public class HideCategoriesActivity extends ListActivity {
    private static final String TAG = "HideCategoriesActivity";

    private static final boolean DEBUG = FoursquaredSettings.DEBUG;

    private static final int DIALOG_PICK_CATEGORY = 1;

    private Foursquared mApplication;

    private LinearLayout mCategoryLayout;
    //private ImageView mCategoryImageView;
    private TextView mCategoryTextView;
    private ProgressBar mCategoryProgressBar;
    //private TextView mChosenCategories;
    
    private CategoryListAdapter mListAdapter;

    private StateHolder mStateHolder;
    
    private boolean mMadeChanges = false;
    
    private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (DEBUG) Log.d(TAG, "onReceive: " + intent);
            finish();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hide_categories_activity);
        registerReceiver(mLoggedOutReceiver, new IntentFilter(Foursquared.INTENT_ACTION_LOGGED_OUT));

        mApplication = (Foursquared) getApplication();
        
        SeparatedListAdapter mSeparatedListAdapter = new SeparatedListAdapter(this);
        
        mListAdapter = new CategoryListAdapter(this, mApplication.getRemoteResourceManager(), null);

        mSeparatedListAdapter.addSection(getResources().getString(R.string.hide_categories_chosen_categories), mListAdapter);

        getListView().setAdapter(mSeparatedListAdapter);
        
        final Context context = this;
        
        getListView().setOnItemLongClickListener(new OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            	final Category category = (Category) parent.getAdapter().getItem(position);

            	AlertDialog.Builder builder = new AlertDialog.Builder(context);
            	
            	builder.setMessage(getResources().getString(R.string.hide_categories_remove_category, category.getNodeName()))
            	       .setCancelable(false)
            	       .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
            	           public void onClick(DialogInterface dialog, int id) {
            	        	   removeCategory(category);
            	           }
            	       })
            	       .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
            	           public void onClick(DialogInterface dialog, int id) {
            	                dialog.cancel();
            	           }
            	       });
            	AlertDialog alert = builder.create();
            	alert.show();
            	
            	return true;
            }
        });


        //mChosenCategories = (TextView)  findViewById(R.id.hideCategoryChosenCategories);
        mCategoryLayout = (LinearLayout) findViewById(R.id.hideCategoryLayout);
        //mCategoryImageView = (ImageView) findViewById(R.id.hideCategoryIcon);
        mCategoryTextView = (TextView) findViewById(R.id.hideCategoryTextView);
        mCategoryProgressBar = (ProgressBar) findViewById(R.id.hideCategoryProgressBar);
        
        mCategoryLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                showDialog(DIALOG_PICK_CATEGORY);
            }
        });
        mCategoryLayout.setEnabled(false);

        Object retained = getLastNonConfigurationInstance();
        if (retained != null && retained instanceof StateHolder) {
            mStateHolder = (StateHolder) retained;
            mStateHolder.setActivity(this);
            
            refresh();
            
            if (mStateHolder.getCategories() != null && mStateHolder.getCategories().size() > 0) {
                mCategoryLayout.setEnabled(true);
                mCategoryProgressBar.setVisibility(View.GONE);
            }
        } else {
            mStateHolder = new StateHolder();
            mStateHolder.startTaskGetCategories(this);
        }

        Button btnClearList = (Button) findViewById(R.id.clearListOfHiddenCategories);
        btnClearList.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
            	clearList();
            }
        });

    }

    private void removeCategory(Category category) {
    	mStateHolder.removeCategory(category);
    	mMadeChanges = true;
    	refresh();
    }
    
    private void clearList() {
    	mStateHolder.clearChosenCategories();
    	mMadeChanges = true;
    	writeCategoriesToPreferences();
    	refresh();
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mLoggedOutReceiver);
    }
    
    private void readCategoriesFromPreferences() {
    	SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(
                HideCategoriesActivity.this);

    	String categories = settings.getString(Preferences.PREFERENCE_HIDE_CATEGORIES_DATA, null);
    	
    	ArrayList<String> categoryIds = CategoryUtils.getSelectionLevelCategoryIdsFromPreferencesString(categories);

    	if (categoryIds != null && categoryIds.size()>0) {
    		for (String categoryId : categoryIds) {
    			try {
    			    mStateHolder.addChosenCategoryById(categoryId);
    			}
    			catch (FoursquareException fe) {
    				Toast.makeText(this, fe.getMessage(), Toast.LENGTH_LONG).show();
    			}
    		}
    	}
    	
    	refresh();
    }

    private void writeCategoriesToPreferences() {
    	if (!mMadeChanges)
    		return ;
    	
    	SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(
                HideCategoriesActivity.this);
    	
    	String categoriesToSave = CategoryUtils.generatePreferencesString(mStateHolder.getChosenCategories());
    	
    	settings.edit().putString(Preferences.PREFERENCE_HIDE_CATEGORIES_DATA, categoriesToSave).commit();
    	
    	mMadeChanges = false;
    }
    
    @Override
    public void onPause() {
        super.onPause();

        writeCategoriesToPreferences();
    }
    
    private void refresh() {
    	mListAdapter.setGroup(mStateHolder.getChosenCategories());
    }

    
    private void onGetCategoriesTaskComplete(Group<Category> categories, Exception ex) {
        mStateHolder.setIsRunningTaskGetCategories(false);
        try {
            // Populate the categories list now.
            if (categories != null) {
                mStateHolder.setCategories(categories);
                mCategoryLayout.setEnabled(true);
                mCategoryTextView.setText(getResources().getString(R.string.add_venue_activity_pick_category_label));
                mCategoryProgressBar.setVisibility(View.GONE);
                
                readCategoriesFromPreferences();
                
            } else {
                // If error, feed list adapter empty user group.
                mStateHolder.setCategories(new Group<Category>());
                NotificationsUtil.ToastReasonForFailure(this, ex);
            }
        } 
        finally {
        }
        stopIndeterminateProgressBar();
    }
     
    private void stopIndeterminateProgressBar() {
        if (mStateHolder.getIsRunningTaskGetCategories() == false) {
            setProgressBarIndeterminateVisibility(false);
        }
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        /*switch (id) {
            case DIALOG_PICK_CATEGORY:*/

    	// When the user cancels the dialog (by hitting the 'back' key), we
        // finish this activity. We don't listen to onDismiss() for this
        // action, because a device rotation will fire onDismiss(), and our
        // dialog would not be re-displayed after the rotation is complete.
        CategoryPickerDialog dlg = new CategoryPickerDialog(
            this, 
            mStateHolder.getCategories(), 
            ((Foursquared)getApplication()));
        dlg.setOnCancelListener(new OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                CategoryPickerDialog dlg = (CategoryPickerDialog)dialog;
                setChosenCategory(dlg.getChosenCategory());
                removeDialog(DIALOG_PICK_CATEGORY);
                
                refresh();
            }
        });
        return dlg;

        //}
    }
    
    private void setChosenCategory(Category category) {
    	if (category == null)
    		return ;
    	
    	mMadeChanges = true;
    	
        // Record the chosen category.
        if (!mStateHolder.addChosenCategory(category))
	    	Toast.makeText(this, 
    			getResources().getString(R.string.hide_categories_category_already_added, category.getNodeName()),
    			Toast.LENGTH_SHORT).show();

        
        
        // Always show prompt at UI element (NOT previous selection)
        mCategoryTextView.setText(getResources().getString(
                R.string.add_venue_activity_pick_category_label));
    }

    private static class GetCategoriesTask extends AsyncTask<Void, Void, Group<Category>> {

        private HideCategoriesActivity mActivity;
        private Exception mReason;

        public GetCategoriesTask(HideCategoriesActivity activity) {
            mActivity = activity;
        }

        public void setActivity(HideCategoriesActivity activity) {
            mActivity = activity;
        }
        
        @Override
        protected void onPreExecute() {
            mActivity.setProgressBarIndeterminateVisibility(true);
        }

        @Override
        protected Group<Category> doInBackground(Void... params) {
            try {
                Foursquared foursquared = (Foursquared) mActivity.getApplication();
                Foursquare foursquare = foursquared.getFoursquare();
                return foursquare.categories();
            } catch (Exception e) {
                if (DEBUG)
                    Log.d(TAG, "GetCategoriesTask: Exception doing send friend request.", e);
                mReason = e;
            }
            return null;
        }

        @Override
        protected void onPostExecute(Group<Category> categories) {
            if (DEBUG) Log.d(TAG, "GetCategoriesTask: onPostExecute()");
            if (mActivity != null) {
                mActivity.onGetCategoriesTaskComplete(categories, mReason);
            }
        }

        @Override
        protected void onCancelled() {
            if (mActivity != null) {
                mActivity.onGetCategoriesTaskComplete(null,
                        new Exception("Get categories task request cancelled."));
            }
        }
    }

    private static class StateHolder {
        
        private GetCategoriesTask mTaskGetCategories;
        private Group<Category> mCategories;
        private boolean mIsRunningTaskGetCategories;
        //private String mError;

        private Group<Category> mChosenCategories = new Group<Category>();

        public StateHolder() {
            mCategories = new Group<Category>();
            mIsRunningTaskGetCategories = false;
        }

        public void setCategories(Group<Category> categories) {
            mCategories = categories;
        }

        public Group<Category> getCategories() {
            return mCategories;
        }
        
        public void startTaskGetCategories(HideCategoriesActivity activity) {
            mIsRunningTaskGetCategories = true;
            mTaskGetCategories = new GetCategoriesTask(activity);
            mTaskGetCategories.execute();
        }

        public void setActivity(HideCategoriesActivity activity) {
            if (mTaskGetCategories != null) {
                mTaskGetCategories.setActivity(activity);
            }
        }
        
        public void setIsRunningTaskGetCategories(boolean isRunning) {
            mIsRunningTaskGetCategories = isRunning;
        }
        
        public boolean getIsRunningTaskGetCategories() {
            return mIsRunningTaskGetCategories;
        }
        
        public boolean addChosenCategory(Category category) {
            //mChosenCategory = category;
            if (!mChosenCategories.contains(category))
            	mChosenCategories.add(0, category);
            else 
            	return false;
            
            return true;
        }
        
         public boolean addChosenCategoryById(String id) 
         								throws FoursquareException {
        	Category category = findCategory(id);
        	
        	if (category != null)
        		return addChosenCategory(category);
        	else
        		throw new FoursquareException("Invalid category");
        	
        }
        
        public Group<Category> getChosenCategories() {
        	return mChosenCategories;
        }
        
        public void clearChosenCategories() {
        	mChosenCategories = new Group<Category>();
        }
        
        public void removeCategory(Category category) {
        	mChosenCategories.remove(category);
        }
        
        /*public String getError() {
            return mError;
        }
        
        public void setError(String error) {
            mError = error;
        }*/
        
        private Category findCategory(String id) {
        	for (Category cat : mCategories) {
        		Category found = findCategory(id, cat);

        		if (found != null)
        			return found;
        	}
        	
        	return null;
        }
        
        private Category findCategory(String id, Category category) {
        	if (id.equals(category.getId())) 
        		return category;
        	
        	Group<Category> children = category.getChildCategories();
        	
        	if (children != null && children.size() > 0)
        	{
        		for (Category child : children) {
        			Category found = findCategory(id, child);
        			
        			if (found != null)
        				return found;
        		}
        	}
        	
        	return null;
        }
    }
}
